<template>
  <div class="quill-edit">
    <div
      :id="elementId"
      style="max-height: 150px; overflow: auto; min-height: 70px"
      @click="applyMentionHighlight"
    ></div>
    <div v-if="showSelect" :style="selectStyle" class="select-container" @focus="showSelect = true">
      <el-select
        v-model="variateValue"
        placeholder="请选择"
        size="small"
        filterable
        @change="handleSelectChange"
      >
        <el-option v-for="item in variateList" :key="item" :label="item" :value="item"/>
      </el-select>
    </div>
  </div>
</template>

<script setup lang="ts" name="QuillEdit">
import Quill from 'quill';
import 'quill/dist/quill.snow.css';
import { Delta } from 'quill/core';
import { nextTick, ref, watch, onUnmounted } from 'vue';
import {RepositoryNodeInputVariables} from '@/view/graph/model/type';

const props = withDefaults(
  defineProps<{
    message: string;
    elementId: string;
    keyId: number;
    input_variables: RepositoryNodeInputVariables[];
  }>(),
  {
    message: '请输入内容',
    elementId: '',
    keyId: 0,
    input_variables: () => []
  }
);
const emits = defineEmits(['textChange']);

const variateList = ref<string[]>([]);
const input_variables = ref<RepositoryNodeInputVariables[]>([]);
let quillEditor: Quill | null = null;
const editorOption = ref({
  modules: {
    toolbar: false
  },
  theme: 'snow',
  placeholder: props.message
});

const variateValue = ref();
const showSelect = ref(false);
const selectStyle = ref({});

watch(
  input_variables,
  value => {
    variateList.value = value
      .map((item: RepositoryNodeInputVariables) => item.variable)
      .filter((item: string) => item !== '');
    applyMentionHighlight();
  },
  {
    immediate: true,
    deep: true
  }
);

onUnmounted(() => {
  quillEditor?.disable();
});

/**
 * 初始化编辑器
 * @param value
 */
function init(value: string, list: RepositoryNodeInputVariables[]) {
  nextTick(() => {
    quillEditor = new Quill(
      document.getElementById(props.elementId as string) as HTMLElement,
      editorOption.value
    );
    quillEditor.on('text-change', handleTextChange);
    quillEditor?.setText(value, 'user');
    input_variables.value = list;
  });
}

/**
 * 监听用户输入信息，并设置提及坐标
 * @param delta
 * @param oldDelta
 * @param source
 */
function handleTextChange(delta: Delta, oldDelta: Delta, source: string) {
  if (source === 'user') {
    const lastOp = delta.ops[delta.ops.length - 1];
    if (lastOp?.insert === '{') {
      const range = quillEditor?.getSelection(true);
      if (range) {
        const bounds = quillEditor?.getBounds(range);
        selectStyle.value = {
          top: `${bounds?.bottom}px`,
          left: `${bounds?.left}px`
        };
      }
      showSelect.value = true;
    }
  }
  applyMentionHighlight();
  emits(
    'textChange',
    quillEditor?.getText() && quillEditor?.getText()?.length <= 1 ? '' : quillEditor?.getText(),
    props.keyId
  );
}

/**
 * 高亮
 * 匹配{{}}
 * 匹配<>
 */
function applyMentionHighlight() {
  if (!quillEditor) {
    return;
  }
  if (quillEditor.getText().length > 1) {
    const str = quillEditor.getText();
    quillEditor.formatText(
      0,
      str.length,
      {
        color: '#303133'
      },
      'silent'
    );
    const list = variateList.value.map(item => {
      return {
        key: item,
        label: item
      };
    });
    const pattern = new RegExp(`\\{\\{(${list.map(item => item.key).join('|')})\\}\\}`, 'g');
    let match;
    while ((match = pattern.exec(str)) !== null) {
      const contentInsideBrackets = match[1];
      const matchedItem = list.find(item => item.key === contentInsideBrackets);
      const startIndex = match.index; // 获取匹配到的双括号的起始下标
      const endIndex = match[0].length; // 获取匹配到的双括号的结束下标
      if (matchedItem) {
        quillEditor.formatText(
          startIndex,
          endIndex,
          {
            color: '#FF8E18'
          },
          'silent'
        );
      }
    }
  }
}

/**
 * 保存选中的提及
 * @param mention
 */
function handleSelectChange(mention: string) {
  if (!quillEditor) {
    return;
  }
  const range = quillEditor.getSelection(true);
  if (range) {
    quillEditor.insertText(range.index, `{${mention}}}`);
    setTimeout(() => {
      quillEditor?.focus();
    });
  }
  showSelect.value = false;
  variateValue.value = '';
}

/**
 * 设置编辑器内容
 * @param value
 */
function setValue(value: string) {
  quillEditor?.setText(value, 'user');
}

defineExpose({
  init,
  showSelect,
  applyMentionHighlight
});
</script>

<style scoped lang="scss">
.quill-edit {
  position: relative;
  width: 100%;
}
.select-container {
  position: absolute;
  z-index: 1000;
  width: 150px;
}
.ql-container.ql-snow {
  border: 1px solid #dcdfe6;
  border-radius: 4px;
}
</style>
